using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Text.Json;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.EntityFrameworkCore;
using Microsoft.IdentityModel.Tokens;
using Microsoft.OpenApi.Models;
using net_work.Common;
using net_work.Config;
using net_work.IRepository.System;
using net_work.Middleware;
using net_work.Repository.Sys;
using net_work.Repository.System;
using net_work.Rules.Utils;
using net_work.Service.BackgroundTask;
using net_work.Service.BackgroundTask.Handler;
using net_work.Service.Sys;
using SixLabors.Fonts;
using StackExchange.Redis;

namespace net_work;

public class Program
{
    public static void Main(string[] args)
    {
        var builder = WebApplication.CreateBuilder(args);

        // 读取配置文件
        builder.Configuration
            .AddEnvironmentVariables(); // 添加环境变量支持

        // 配置分布式缓存
        builder.Services.AddStackExchangeRedisCache(options =>
        {
            options.Configuration = builder.Configuration["Redis:ConnectionString"];

            // 检查是否有环境变量 REDIS_PASSWORD
            var redisPassword = Environment.GetEnvironmentVariable("REDIS_PASSWORD");

            // 如果环境变量中有密码，动态拼接到连接字符串
            if (!string.IsNullOrEmpty(redisPassword))
            {
                options.Configuration += $",password={redisPassword}";
            }
        });

        // 配置 Redis 连接，用于访问 Redis 数据结构（队列等）
        builder.Services.AddSingleton<IConnectionMultiplexer>(_ =>
        {
            var connectionString = builder.Configuration["Redis:ConnectionString"];

            // 如果有密码，添加到连接字符串中
            var redisPassword = Environment.GetEnvironmentVariable("REDIS_PASSWORD");
            if (!string.IsNullOrEmpty(redisPassword))
            {
                connectionString += $",password={redisPassword}";
            }

            return ConnectionMultiplexer.Connect(connectionString ?? throw new InvalidOperationException());
        });

        // 配置 JWT
        var jwtSettings = builder.Configuration.GetSection("JwtSettings");
        builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
            .AddJwtBearer(options =>
            {
                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuer = true,
                    ValidateAudience = true,
                    ValidateIssuerSigningKey = true,
                    ValidIssuer = jwtSettings["Issuer"],
                    ValidAudience = jwtSettings["Audience"],
                    IssuerSigningKey =
                        new SymmetricSecurityKey(
                            Encoding.UTF8.GetBytes(jwtSettings["Key"] ?? throw new InvalidOperationException())),
                    ClockSkew = TimeSpan.Zero, // 去除默认的时间偏移
                    NameClaimType = JwtRegisteredClaimNames.Name,
                    RoleClaimType = ClaimTypes.Role
                };
                options.Events = new JwtBearerEvents
                {
                    // 认证未通过
                    OnChallenge = context =>
                    {
                        context.HandleResponse(); // 结束响应的处理

                        context.Response.StatusCode = 401;
                        context.Response.ContentType = "application/json";
                        var challengeResponse = new { error = "未授权访问，请先登录。" };
                        context.Response.WriteAsync(JsonSerializer.Serialize(challengeResponse));

                        return Task.CompletedTask;
                    },
                    // 授权失败时（例如权限不足）
                    OnForbidden = context =>
                    {
                        context.Response.StatusCode = 403;
                        context.Response.ContentType = "application/json";
                        var forbiddenResponse = new { error = "权限不足，禁止访问。" };
                        return context.Response.WriteAsync(JsonSerializer.Serialize(forbiddenResponse));
                    }
                };
            });

        // 添加 Swagger（仅在开发环境启用）
        if (builder.Environment.IsDevelopment())
        {
            builder.Services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "API", Version = "v1" });
                c.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                {
                    Name = "Authorization",
                    Type = SecuritySchemeType.Http,
                    Scheme = "Bearer",
                    BearerFormat = "JWT",
                    In = ParameterLocation.Header,
                    Description = "JWT 格式：Bearer {token}"
                });
                c.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference
                            {
                                Type = ReferenceType.SecurityScheme,
                                Id = "Bearer"
                            }
                        },
                        Array.Empty<string>()
                    }
                });
            });
        }

        // 注册 ApplicationDbContext 并使用 MySQL
        builder.Services.AddDbContext<ApplicationDbContext>(options =>
        {
            // 配置 MySQL
            options.UseMySql(
                builder.Configuration.GetSection("MySQL")["ConnectionString"],
                ServerVersion.AutoDetect(builder.Configuration.GetSection("MySQL")["ConnectionString"])
            );

            // 在开发环境启用详细错误和敏感数据日志
            if (builder.Environment.IsDevelopment())
            {
                options.EnableDetailedErrors()
                    .EnableSensitiveDataLogging();
            }
        });

        // 添加 Authorization
        builder.Services.AddAuthorization();

        // 添加 Controllers
        builder.Services.AddControllers()
            .AddJsonOptions(options =>
            {
                // 配置枚举值使用名称而非整数
                options.JsonSerializerOptions.Converters.Add(
                    new System.Text.Json.Serialization.JsonStringEnumConverter());
            });

        builder.Services.AddEndpointsApiExplorer();

        // 添加用户上下文（UserContext）
        builder.Services.AddHttpContextAccessor();
        builder.Services.AddScoped<IUserContext, UserContext>();

        // 添加事务管理器
        builder.Services.AddScoped<ITransactionManager, TransactionManager>();

        // 注册 AutoMapper
        builder.Services.AddAutoMapper(typeof(Program));

        // 注册队列服务
        builder.Services.AddSingleton<ITaskQueue, RedisTaskQueue>();

        // 注册任务处理服务
        builder.Services.AddHostedService<TaskProcessor>();

        // 配置后台服务异常行为
        builder.Services.Configure<HostOptions>(options =>
        {
            // 设置为 Ignore，避免后台服务异常导致主机停止
            options.BackgroundServiceExceptionBehavior = BackgroundServiceExceptionBehavior.Ignore;
        });

        // 注册任务处理工厂
        builder.Services.AddSingleton<TaskHandlerFactory>();

        // 注册规则引擎
        builder.Services.AddSingleton<IRuleEngineUtils, RuleEngineUtils>();

        // 注册任务处理程序
        builder.Services.Scan(scan => scan
            .FromAssembliesOf(typeof(ImportTeacherExcelTaskHandler))
            .AddClasses(classes => classes.Where(t => t.Name.EndsWith("TaskHandler", StringComparison.Ordinal)))
            .AsSelf()
            .WithSingletonLifetime());

        // 注册仓储类
        builder.Services.Scan(scan => scan
            .FromAssembliesOf(typeof(UserRepository)) // 指定一个类型所在的程序集
            .AddClasses(classes => classes.Where(t => t.Name.EndsWith("Repository", StringComparison.Ordinal)))
            .AsImplementedInterfaces()
            .WithScopedLifetime());

        // 注册服务类
        builder.Services.Scan(scan => scan
            .FromAssembliesOf(typeof(UserService)) // 指定一个类型所在的程序集
            .AddClasses(classes => classes.Where(t => t.Name.EndsWith("Service", StringComparison.Ordinal)))
            .AsImplementedInterfaces()
            .WithScopedLifetime());

        builder.Services.AddSingleton<FontCollection>(_ =>
        {
            var fontCollection = new FontCollection();
            fontCollection.AddSystemFonts(); // 加载系统字体
            return fontCollection;
        });

        var app = builder.Build();

        // 配置中间件
        if (app.Environment.IsDevelopment())
        {
            app.UseSwagger();
            app.UseSwaggerUI();
        }

        app.UseHttpsRedirection();

        // 配置跨域
        app.UseCors(corsConfig =>
        {
            corsConfig.AllowAnyOrigin()
                .AllowAnyMethod()
                .AllowAnyHeader();
        });


        // 添加认证和授权中间件
        app.UseAuthentication();
        app.UseAuthorization();

        // 注册中间件
        app.UseMiddleware<GlobalExceptionMiddleware>();

        app.MapControllers();

        app.Run();
    }
}